#!/bin/bash

# 构建依赖的service的脚本，脚本会尽可能地不破坏你本地的内容。请放心使用。
# 使用的时候需要在你的环境变量配置 frame 的仓库地址，环境变量 FRAME_REPOSITORY ，
# 如果不配置，那么默认是 https://github.com/smarty-kiki/frame.git
#
# service的引入是通过读取项目根目录dep_service_list完成的。
# dep_service_list格式注意以下几点：
# 1.空白行会被忽略
# 2.#开头的是注释，不是#开头的是配置项目
# 3.配置项目格式是（注意中间有空格）：服务名称 服务仓库地址
#
# 此外需要注意，本脚本必须用Bash shell执行

RANDOM_NUMBER_FUNCTION_CREATE=""
create_random_number_with_length()
{
    RANDOM_NUMBER_FUNCTION_CREATE=""
    for((i=0;i<$1;i++));
    do
        RANDOM_NUMBER_FUNCTION_CREATE=$RANDOM_NUMBER_FUNCTION_CREATE${RANDOM:0:1}
    done
}

get_relative_path()
{
    command -v python3 &>/dev/null
    if [ $? -eq 0 ]
    then
        python3 -c "import os.path; print(os.path.relpath('$1', '$2'))"
    else
        python -c "import os.path; print os.path.relpath('$1', '$2')"
    fi
    if [ $? -ne 0 ]
    then
        echo "找不到Python命令或Python命令出错，终止执行" 1>&2
        exit
    fi
}

# 写入ROOT_DIR的.gitignore文件，第一个参数是要忽略的文件
add_gitignore()
{
    php -r '
        $root_dir = "";
        $ignore_file = "";
        foreach ($_SERVER["argv"] as $argv) {
            if (0 === strpos($argv, "ROOT_DIR=")) {
                $root_dir = ltrim($argv, "ROOT_DIR=");
            }
            if (0 === strpos($argv, "IGNORE_FILE=")) {
                $ignore_file = ltrim($argv, "IGNORE_FILE=");
            }
        }
        if (empty($root_dir) || empty($ignore_file) || !is_dir($root_dir)) {
            exit(1);
        }
        if (!is_file("{$root_dir}/.gitignore")) {
            file_put_contents("{$root_dir}/.gitignore", $ignore_file);
            exit();
        }
        if (false === ($fp = fopen("{$root_dir}/.gitignore", "r+b"))) {
            exit(2);
        }
        $end_of_line = false;
        while (false !== ($line = fgets($fp))) {
            if ($ignore_file == $line) {
                fclose($fp);
                exit();
            }
            $end_of_line = substr($line, -1, 1) === PHP_EOL;
        }
        fwrite($fp, ($end_of_line ? "" : PHP_EOL) . $ignore_file);
        fclose($fp);
    ' ROOT_DIR="$ROOT_DIR" IGNORE_FILE=$1
    if [ $? -ne 0 ]
    then
        echo "添加忽略内容到.gitignore文件失败，终止执行" 1>&2
        exit
    fi
}

# 检出分支，第一个参数是本地仓库目录，第二个参数是分支名称
checkout_branch()
{
    REPOSITORY_DIR=$1
    TARGET_BRANCH=$2
    if [ -n "$TARGET_BRANCH" ]
    then
        cd $REPOSITORY_DIR
        local GIT_STATUS=`git status -s`
        if [ -n "$GIT_STATUS" ]
        then
            echo "文件夹$REPOSITORY_DIR内存在尚未提交的代码，请处理后再执行，脚本终止。" 1>&2
            exit
        fi
        git remote set-branches origin $TARGET_BRANCH
        git fetch --depth=1 origin $TARGET_BRANCH
        git checkout -b $TARGET_BRANCH origin/$TARGET_BRANCH
        cd - > /dev/null
    else
        echo "checkout_branch参数太少，脚本终止" 1>&2
        exit
    fi
}

# 克隆项目，第一个参数是仓库地址，第二个参数是克隆到本地目录名称，第三个参数是项目名称，在这儿没啥实际作用
git_clone()
{
    if [ -e "$2" ]
    then
        echo "目录 $2 已经存在，停止git克隆操作。脚本终止。" 1>&2
        exit
    fi
    echo "git clone --depth=1 $1 $2"
    git clone --depth=1 $1 $2 || (echo "获取项目 $3 失败" && exit)
}

# 一般这个命令是创建frame目录
# 克隆FRAME_REPOSITORY到本地的FRAME_DIR目录，然后进入FRAME_DIR，切换到分支BRANCH
dep_frame_file()
{
    git_clone $FRAME_REPOSITORY $FRAME_DIR frame
    if [ -n "$BRANCH" ]
    then
        checkout_branch $FRAME_DIR $BRANCH
    fi
    add_gitignore '/frame'
}

# 去外层目录克隆frame或者更新并切换到给定分支，然后建立软连接
dep_frame_link()
{
    if [ -e "$FRAME_DIR" ]
    then
        echo "目录 $FRAME_DIR 已经存在，请手动更新。脚本终止。" 1>&2
        exit
    fi
    local FRAME_TMP_DIR=$ROOT_DIR/../frame

    if [ ! -d $FRAME_TMP_DIR ]
    then
        git_clone $FRAME_REPOSITORY $FRAME_TMP_DIR frame
    fi
    if [ -n "$BRANCH" ]
    then
        checkout_branch $FRAME_TMP_DIR $BRANCH
    fi
    ln -fs ../frame $FRAME_DIR
    add_gitignore '/frame'
}

# 构建本地项目需要的service文件和文件夹，文件连接
dep_build_file()
{
    create_random_number_with_length 15
    local SERVICE_NAME=$1
    local SERVICE_REPOSITORY=$2
    local SERVICE_TMP_DIR="$ROOT_DIR/.dep_tmp_dir$RANDOM_NUMBER_FUNCTION_CREATE"

    if [ -e "$SERVICE_TMP_DIR" ]
    then
        echo "等会儿要删除的临时目录 $SERVICE_TMP_DIR 已经存在，脚本终止。" 1>&2
        exit
    fi
    if [ -e "$DEP_CLIENT_DIR/$SERVICE_NAME" ]
    then
        echo "目录 $DEP_CLIENT_DIR/$SERVICE_NAME 已经存在。跳过"
        return
    fi
    if [ -e "$DEP_DOMAIN_DIR/$SERVICE_NAME" ]
    then
        echo "目录 $DEP_DOMAIN_DIR/$SERVICE_NAME 已经存在。跳过"
        return
    fi

    git_clone $SERVICE_REPOSITORY $SERVICE_TMP_DIR $SERVICE_NAME
    if [ -n "$BRANCH" ]
    then
        checkout_branch $SERVICE_TMP_DIR $BRANCH
    fi

    cp -r $SERVICE_TMP_DIR/client $DEP_CLIENT_DIR/$SERVICE_NAME
    echo "include __DIR__.'/$SERVICE_NAME/load.php';" >> $DEP_CLIENT_DIR/load.php

    cp -r $SERVICE_TMP_DIR/domain $DEP_DOMAIN_DIR/$SERVICE_NAME
    echo "include __DIR__.'/$SERVICE_NAME/load.php';" >> $DEP_DOMAIN_DIR/load.php

    rm -rf $SERVICE_TMP_DIR
}

# 构建服务依赖，链接
dep_build_link()
{
    SERVICE_NAME=$1
    SERVICE_REPOSITORY=$2
    SERVICE_TMP_DIR=$ROOT_DIR/../$SERVICE_NAME

    if [ -e "$DEP_CLIENT_DIR/$SERVICE_NAME" ]
    then
        echo "目录 $DEP_CLIENT_DIR/$SERVICE_NAME 已经存在。跳过"
        return
    fi
    if [ -e "$DEP_DOMAIN_DIR/$SERVICE_NAME" ]
    then
        echo "目录 $DEP_DOMAIN_DIR/$SERVICE_NAME 已经存在。跳过"
        return
    fi

    if [ ! -d $SERVICE_TMP_DIR ]
    then
        git_clone $SERVICE_REPOSITORY $SERVICE_TMP_DIR $SERVICE_NAME
    fi
    if [ -n "$BRANCH" ]
    then
        checkout_branch $SERVICE_TMP_DIR $BRANCH
    fi

    ln -fs `get_relative_path $SERVICE_TMP_DIR/client $DEP_CLIENT_DIR` $DEP_CLIENT_DIR/$SERVICE_NAME
    echo "include __DIR__.'/$SERVICE_NAME/load.php';" >> $DEP_CLIENT_DIR/load.php

    ln -fs `get_relative_path $SERVICE_TMP_DIR/domain $DEP_DOMAIN_DIR` $DEP_DOMAIN_DIR/$SERVICE_NAME
    echo "include __DIR__.'/$SERVICE_NAME/load.php';" >> $DEP_DOMAIN_DIR/load.php
}

# ------------------ start --------------------

TYPE=$1
if [ -z "$TYPE" ]
then
    echo "用法 $0 模式 [依赖项目分支]"
    echo "模式:"
    echo ""
    echo "  link  依赖关系和框架以软链方式引入"
    echo "  file  依赖关系和框架以文件方式引入"
    echo ""
    echo "1.依赖项目分支可以不传，不传使用依赖项目的默认分支"
    echo "2.link模式会克隆远程仓库到当前目录的上一层目录"
    echo ""
    exit
fi

BRANCH=$2

ROOT_DIR="$(cd "$(dirname $0)" && pwd)"/../..

# ------------------ add frame ------------------
FRAME_DIR=$ROOT_DIR/frame

if [ -z "$FRAME_REPOSITORY" ]
then
    FRAME_REPOSITORY=https://github.com/smarty-kiki/frame.git
fi

echo "即将处置frame框架，仓库配置地址为 $FRAME_REPOSITORY"
if [ -e "$FRAME_DIR" ]
then
    echo "$FRAME_DIR 存在，跳过处置frame步骤" 1>&2
else
    dep_frame_$TYPE
    echo "处置frame框架完成"
fi

# ------------------ add depend ------------------
DEP_FILE=$ROOT_DIR/dep_service_list
if [ ! -f $DEP_FILE ]
then
    echo "$DEP_FILE 无配置，不加载相关依赖系统"
    exit
fi

DEP_CLIENT_DIR=$ROOT_DIR/dep_client
DEP_DOMAIN_DIR=$ROOT_DIR/dep_domain

for d in /dep_client /dep_domain
do
    dir=$ROOT_DIR/$d
    if [ ! -e "$dir" ]
    then
        echo "创建并忽略目录$dir"
        mkdir -p $dir
        echo "<?php" > $dir/load.php
        echo "" >> $dir/load.php
        add_gitignore $d
    fi
done

cat $DEP_FILE | grep -v '^#' | grep -v '^\s*$' | while read arg
do
    if [ -n "$arg" ]
    then
        echo "创建服务项 $arg"
        dep_build_$TYPE $arg
    fi
done
